/**
 * @brief    频响分析测试
 *
 * @version  0.1
 * @author   wjw
 * @date     2025.04.11
 *         _
 *     ___| |__   ___ _ __   __ _  ___  _ __   __ _
 *    / __| '_ \ / _ \ '_ \ / _` |/ _ \| '_ \ / _` |
 *    \__ \ | | |  __/ | | | (_| | (_) | | | | (_| |
 *    |___/_| |_|\___|_| |_|\__, |\___/|_| |_|\__, |
 *                          |___/             |___/
 * @copyright (c) 2025 by 神工仿真, All Rights Reserved.
 */
#pragma once
#include "gtest/gtest.h"
#include "Utility/FileSystem/SGFileSystem.h"
#include "DBManager/IService/Input/Dynamic/IFREQ1Service.h"

#include "SGFem/Task/Kernel/MModel.h"
#include "../FrequencyDirectSolver.h"

using namespace SG::Utility::FileSystem;
using SG::DataStructure::Common::Status;
using SG::DataStructure::FEM::Project;
using namespace SG::DBManager;

extern std::shared_ptr<DBServiceFactory> DB_SERVICEFACTORY;

struct FrequencyAnalysisTestData
{
    std::string                   m_inputFile;    ///< 输入文件名称
    std::vector<double>           m_modalTarget;  ///< Nastran响应结果
    SG::Algebra::Real_t           m_error;        ///< 误差上限
    SG::DataStructure::Common::Id m_ForceID;      ///< 载荷作用点全局ID
};

class FrequencyTest : public ::testing::TestWithParam<FrequencyAnalysisTestData>
{
  protected:
    void SetUp () override
    {
        modelPath = getTestDataPath ("SGFem/ModalAnalysis/");
    }

    void TearDown () override
    {
        DB_SERVICEFACTORY->ClearDatabase ();
    }
    std::string modelPath;  ///< 输入模型文件路径
};

TEST_P (FrequencyTest, ComputeResponseAsExpect)
{
    auto para = GetParam ();
    // Input
    Project project;
    project.m_modelFilePath = modelPath;
    project.m_modelFileName = para.m_inputFile;
    auto posi               = para.m_inputFile.find ('.');
    project.m_jobName       = para.m_inputFile.substr (0, posi);

    DB_SERVICEFACTORY->ClearDatabase ();
    SG::Import::SGImporter importer (DB_SERVICEFACTORY);
    auto                   status = importer.Import (project.m_modelFilePath + project.m_modelFileName);
    ASSERT_EQ (status, Status::STATUS_Success);

    // Test data
    // 获取模型中所有的subCase
    auto                            subcaseIds = DB_SERVICEFACTORY->get<ISubcaseService> ()->GetAllSubcaseID ();
    FrequencyDirectSolver solver;
    solver.Solve (DB_SERVICEFACTORY, project, subcaseIds[0]);

    // 创建 model 是为了获取结果数据
    Kernel::MModel ModelTest (SG::DataStructure::FEM::SOLType::SOL_SEDFREQ, DB_SERVICEFACTORY);
    auto                            para1      = DB_SERVICEFACTORY->get<ISubcaseService> ()->FindSubCase (subcaseIds[0]);
    SG::DataStructure::FEM::Subcase subcase (para1);


    std::vector<SG::DataStructure::FEM::FREQ1Data> FREQ1Data;
    ASSERT_EQ (Status::STATUS_Success, DB_SERVICEFACTORY->get<IFREQ1Service> ()->FindBySId (subcase.GetFrequencyId (), _OUT FREQ1Data));

    SG::Algebra::ComplexVec_t V;
    std::vector<double>       wSet = getfreqVector(FREQ1Data);
    std::vector<double>       modalTest;  // 将存储复数的幅值

    for (const auto& w : wSet)
    {
        ModelTest.GetDisplacement (subcaseIds[0], w, _OUT V);

        // 计算复数的幅值 (magnitude/absolute value)
        double magnitude = std::abs (V (para.m_ForceID));
        modalTest.push_back (magnitude);
    }

    // Target data
    const auto modalTarget = para.m_modalTarget;

    // Check 计算相对误差
    double numerator_norm   = 0.0;
    double denominator_norm = 0.0;
    double diff;
    for (size_t i = 0; i < modalTest.size (); ++i)
    {
        diff = modalTest[i] - modalTarget[i];
        numerator_norm += diff * diff;
        denominator_norm += modalTarget[i] * modalTarget[i];
    }
    numerator_norm        = std::sqrt (numerator_norm);
    denominator_norm      = std::sqrt (denominator_norm);
    double relative_error = numerator_norm / denominator_norm;
    ASSERT_LE (relative_error, para.m_error);
};
std::vector<double> TargetDirect1 = { 0.008706, 0.006456, 0.004816, 0.003764, 0.003066, 0.002578, 0.002220, 0.001947, 0.001733,
                                      0.001561, 0.001420, 0.001302, 0.001201, 0.001116, 0.001041, 0.000976, 0.000918, 0.000867,
                                      0.000821, 0.000780, 0.000743, 0.000709, 0.000678, 0.000650, 0.000623, 0.000599, 0.000577,
                                      0.000556, 0.000537, 0.000519, 0.000502, 0.000487, 0.000472, 0.000458, 0.000445, 0.000432,
                                      0.000421, 0.000410, 0.000399, 0.000389, 0.000379, 0.000370, 0.000362, 0.000353, 0.000346,
                                      0.000338, 0.000331, 0.000324, 0.000317, 0.000311, 0.000305 };

SG::Algebra::Real_t           errorDirect1   = 0.000148;
SG::DataStructure::Common::Id ForceIDDirect1 = 1172;
INSTANTIATE_TEST_CASE_P (DirectFrequencyAnalysis,
                         FrequencyTest,
                         testing::Values (FrequencyAnalysisTestData{
                             "DirectFrequedcyModel.bdf", TargetDirect1, errorDirect1, ForceIDDirect1 }));
